<template>
  <div class="cm-field" :class="['cm-field__'+prop, 'cm-field--' + (cmfield__readonly ? 'readonly' : '')]">
<!--    {{getRules()}}-->
    <el-form-item
        v-bind="ui ? ui.form_item : {}"
        :prop="cmfield_prop"
        :rules="getRules()" v-if="cmfield_prop && state.comReady">
<!--      {{prop}} {{cmfield_prop}}-->
      <!--    <el-input v-model="state.value" @input="onInput"></el-input>-->
      <!--    <test-input-widget v-model="state.value" @input="onInput"></test-input-widget>-->
      <!--    {{widgetUUID}}-->
      <template v-if="showLabel(ui)" v-slot:label="">
        <div class="cm-filed__label">{{getLabel()}}</div>
      </template>
<!--      {{widgetUUID}}-->
      <component :is="widgetUUID"></component>
      <div class="cm-filed__desc"><div>{{getDesc()}}</div></div>
    </el-form-item>
  </div>
</template>

<script>
import {createTemCmFieldCom} from "./cm-field-core";

export default {
  name: 'CmField',
  props: {
    prop: String,
    label: String,
    type: String,
    formPath: String,
    parentModel: null,
    arrayModel: null,
    modelValue: null,
    part_key: String,
    context: null,
    globalConfig: null,
    selfpath: String,
    configPath: String,
    pathArr: Array,
    prop_config: Object,
    ui: {
      type: Object,
      default() {
        return {};
      },
    },
    rules: {
      type: Array,
      default() {
        return [];
      },
    },
    slotContent: null,
    noLabel: Boolean
  },
  computed: {
    cmfield__readonly() {
      let readonly = this.cmfield__globalUIConfig?.globals?.readonly
      if (readonly) {
        return true
      }
    },
    cmfield__disabled() {
      let readonly = this.cmfield__globalUIConfig?.globals?.disabled
      if (readonly) {
        return true
      }
    },
  },
  setup(props, { emit }) {
    const {inject, onBeforeMount, onBeforeUnmount, provide, reactive, watch, getCurrentInstance} = globalThis.vueCompositionAPI;
    let instanse = getCurrentInstance();
    let meta = globalThis.ZForm.getZFormMeta (instanse);
    // console.log(meta)
    let ZY_EXT = globalThis.ZY_EXT;
    let lodash = ZY.lodash;
    let curFormCon = inject('curFormCon');
    let prop_config = props.prop_config ?? {};


    let globalConfig = curFormCon.getUI_CONFIG(props.globalConfig)
    let globalUIConfig = globalConfig?.def?.ui ?? {}

    // console.log(globalUIConfig)

    let evat_utils = {
      CALC_DATE(date1, date2) {
        /*@param date1 {Date|string (Date format)} 结束日期

  @param date2 {Date|string (Date format)} 开始日期

  @returns {null|*}
  */
        if (date1 && date2) {
          return ZY.Time.subtract2Date(date1, date2).asHours();
        }
        return null;
      }
    }

    const evalContext = function (model) {
      let evalobj = {
        ...globalThis.COM_FORM_COMMON_EVAL_FUNS,
        MODEL(v, defaultVal) {
          return lodash.get(model, v, defaultVal)
        },
        M(pathArr, defaultVal = '') {
          let s_path = ZY.getObjPathFromPathArr(pathArr);
          return lodash.get(model, s_path, defaultVal)
        },
      }
      evalobj.CALC_TIME = function (p1, p2) {
        let v1 = evalobj.M(p1);
        let v2 = evalobj.M(p2);
        return evat_utils.CALC_DATE(v1, v2)
      }
    }

    let computedFun = prop_config.computedFun ?? ''
    ZCONSOLE.log('cmfield computedFun', computedFun, props, )

    if (computedFun) {
      let keys = []
      let modelFun = Array.of(...computedFun.matchAll(/(MODEL\()[^\\)]*\)/g))
      let modelStr = modelFun.map( v => v[0]).join(';')

      let allPaths = []

      // let map = new Map()
      let mFun = Array.of(...computedFun.matchAll(/(M\()[^\\)]*\)/g))
      let mStr = mFun.map( v => v[0]).join(';')
      // console.log(mStr)
      ZY_EXT.eval5(modelStr, {
        MODEL(key) {
          // console.log(key)
          keys.push(key)
        },
      });
      ZY_EXT.eval5(mStr, {
        M(key) {
          let mKeys = []
          // console.log(key)
          let s_path  = ZY.getObjPathFromPathArr(key)
          mKeys.push({
            pathArr: key,
            s_path: s_path
          })
          allPaths.push(s_path)
          // map.set(s_path, mKeys)
        },
      });
      if (keys.length > 0) {
        curFormCon.registerWatchHandle(keys, {
          run(model) {
            // console.log(computedFun)
            let val = ZY_EXT.eval5(computedFun, evalContext(model));
            let str = ZY.getObjPathFromPathArr(props.pathArr);
            // console.log(str)
            lodash.set(model, str, val)
          }
        })
      }
      let str = ZY.getObjPathFromPathArr(props.pathArr);
      curFormCon.registerHook('afterUpdate',  str,function ({partName, model, s_path, getCmFieldContext, pathArr, e}) {
        if (allPaths.includes(s_path)) {
          let val = ZY_EXT.eval5(computedFun, evalContext(model));

          let last = props.pathArr[props.pathArr.length - 1]
          let lastCmFieldContext = getCmFieldContext(last)
          if (lastCmFieldContext) {
            // console.log('触发',  last, lastCmFieldContext)
            lastCmFieldContext.zfield__setAndUpdate(val)
          }
          // let str = ZY.getObjPathFromPathArr(props.pathArr);
          // lodash.set(model, str, 'sdsd')
        }
      })
    }

    let isLocked = false;
    // const context = props.context;
    const uuid = 'cm-field-' + ZY.cid(10);
    let widgetUUID = uuid + '__widget__' + ZY.rid(10).toLowerCase()


    let state = reactive({
      comReady: false,
      value: props.modelValue ?? null,
    })

    // console.log(lock)

    function onInput(v) {
      // console.log('sdsdsds', v, isLocked)
      if (!isLocked) {
        isLocked = true;
        emit('val-change', v);
        emit('valchange', v);
        setTimeout(() => {
          // ZY.PubSub.publish('value-change', v)
          isLocked = false
        },150);
      }
    }
    let onChange = onInput

    function initValue(oldVal) {
      if (Array.isArray(oldVal)) {

        // console.log(Array.isArray(oldVal), oldVal, state.value)
        // if (typeof state.value === 'undefined' || state.value === null) {
        //   return oldVal
        // }
        return oldVal
      }
      return state.value
    }

    function getLabel() {
      return lodash.get(props.prop_config, ['ui', 'label'])
    }

    function getDesc() {
      return lodash.get(props.prop_config, ['ui', 'desc'])
    }

    function getRules() {
      return lodash.get(props.prop_config, ['rules'])
    }


    function showLabel() {
      if (props.noLabel) {
        return false
      }
      if (props.ui && props.ui.hiddenLabel) {
        return false;
      }
      return true;
    }

    function resetField(model) {
      let newVal = ZY.lodash.get(model, props.pathArr)
      // console.log('resetField',  ele, newVal)
      ele.value = newVal
    }

    props.self_path = ZY.getObjPathFromPathArr(props.pathArr )


    let ele = null
    let ret =  {
      register(sel) {
        // console.log('cm-field register', sel)
        ele = sel
      },
      curFormCon,
      resetField,
      cmfield_prop: props.pathArr.join('.'),
      cmFieldUUID: uuid,
      state,
      onChange,
      getProps() {
        return props
      },
      initValue,
      cmfield__globalUIConfig: globalUIConfig,
      getRules,
      widgetUUID,
      showLabel,
      getDesc,
      getLabel,
      onInput,
    }

    function getWidgetContext() {
      return ele
    }


    watch(() => props.modelValue, function(newVal) {
      if (!isLocked) {
        // console.log('cmfield watch', newVal, ele)
        // state.value = newVal
        ele.zfield__setVal(newVal);
        if (ele.onModelValueWatch) {
          ele.onModelValueWatch(newVal)
        }
      }
    }, {
    })



    let cmFieldTplMixin = curFormCon.fieldMixin(prop_config, {
      props
    })


    // console.log(cmFieldTplMixin)
    // console.log(props.prop, props.self_path)
    let registerKey = props.self_path

    // console.log('local curFormCon', curFormCon.version)
    curFormCon.register(
        createTemCmFieldCom(widgetUUID, cmFieldTplMixin, {
          outerProps: props,
          prop_config: props.prop_config,
          globalUIConfig
        }),
        registerKey,
        {
          props,
          getWidgetContext,
          resetField
        }
    )

    // meta.CustomDymComponent.register(
    //     createTemCmFieldCom(widgetUUID, cmFieldTpl)
    // )


    onBeforeMount(() => {
      state.comReady = true
    })

    onBeforeUnmount(() => {
      // meta.CustomDymComponent.unRegister(widgetUUID)
      // console.log(widgetUUID)
      curFormCon.unRegister(
          widgetUUID,
          registerKey,
      )
    })

    provide('CurCmField', ret);

    return ret;
  }
}
</script>
